package zzs.generalframework.coder.core.encoder.special.console.service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import zzs.generalframework.coder.common.model.AnnotationInfo;
import zzs.generalframework.coder.common.model.ClassInfo;
import zzs.generalframework.coder.common.model.FieldInfo;
import zzs.generalframework.coder.common.model.MethodInfo;
import zzs.generalframework.util.core.string.StringUtils;

/**
 * @title
 * @description
 * @project zzs-coder
 * @package zzs.generalframework.coder.core.encoder.special.console.service
 * @author zzs
 * @date 2018年1月31日
 * @version 1.0
 */
public class InterfaceCoder
{

	private ClassInfo classInfo = null;

	public InterfaceCoder(String classPackagePath, String acceccModdifier, String classType, String className, Class boClass, Class infoClass)
	{
		ClassInfo classInfo = new ClassInfo();
		classInfo.setClassPackagePath(classPackagePath);
		classInfo.setAcceccModdifier(acceccModdifier);
		classInfo.setClassType(classType);
		classInfo.setClassName(className);
		List<MethodInfo> methodInfoList = new ArrayList<MethodInfo>();
		classInfo.setMethodInfoList(methodInfoList);
		initClassNote(classInfo);
		initSaveMethod(classInfo, boClass);
		initGetMethod(classInfo, infoClass);
		initListMethod(classInfo, infoClass);
		initUpdateMethod(classInfo, boClass);
		initRemoveMethod(classInfo, boClass);
		initCountMethod(classInfo, infoClass);
		this.classInfo = classInfo;
	}

	private void initClassNote(ClassInfo classInfo)
	{
		StringBuffer classNoteBuffer = new StringBuffer();
		classNoteBuffer.append("/**").append("\n");
		classNoteBuffer.append(" * @title").append("\n");
		classNoteBuffer.append(" * @description").append("\n");
		classNoteBuffer.append(" * @project zzs-console").append("\n");
		classNoteBuffer.append(" * @package ").append(classInfo.getClassPackagePath()).append("\n");
		classNoteBuffer.append(" * @author zzs").append("\n");
		classNoteBuffer.append(" * @date 2018年1月31日").append("\n");
		classNoteBuffer.append(" * @version 1.0").append("\n");
		classNoteBuffer.append(" */").append("\n");
		classInfo.setNote(classNoteBuffer.toString());
	}

	private void initSaveMethod(ClassInfo classInfo, Class boClass)
	{
		MethodInfo saveMethodInfo = new MethodInfo();
		List<Class> parameterList = new ArrayList<Class>();
		parameterList.add(boClass);
		saveMethodInfo = initMethod("public", "ConsoleReturnBO", "save" + boClass.getSimpleName().substring(0, boClass.getSimpleName().length() - 2), parameterList, null);
		classInfo.getMethodInfoList().add(saveMethodInfo);
		MethodInfo saveListMethodInfo = new MethodInfo();
		List<Class> parameter2List = new ArrayList<>();
		parameter2List.add(List.class);
		saveListMethodInfo = initMethod("public", "ConsoleReturnBO", "save" + boClass.getSimpleName().substring(0, boClass.getSimpleName().length() - 2), parameter2List, null);
		classInfo.getMethodInfoList().add(saveListMethodInfo);
	}

	private void initGetMethod(ClassInfo classInfo, Class infoClass)
	{
		MethodInfo getMethodInfo = new MethodInfo();
		List<Class> parameterList = new ArrayList<Class>();
		parameterList.add(infoClass);
		getMethodInfo = initMethod("public", "ConsoleReturnBO", "get" + infoClass.getSimpleName().substring(0, infoClass.getSimpleName().length() - 2), parameterList, null);
		classInfo.getMethodInfoList().add(getMethodInfo);
	}

	private void initListMethod(ClassInfo classInfo, Class infoClass)
	{
		MethodInfo listMethodInfo = new MethodInfo();
		List<Class> parameterList = new ArrayList<Class>();
		parameterList.add(infoClass);
		listMethodInfo = initMethod("public", "ConsoleReturnBO", "list" + infoClass.getSimpleName().substring(0, infoClass.getSimpleName().length() - 2), parameterList, null);
		classInfo.getMethodInfoList().add(listMethodInfo);
	}

	private void initUpdateMethod(ClassInfo classInfo, Class boClass)
	{
		MethodInfo updateMethodInfo = new MethodInfo();
		List<Class> parameterList = new ArrayList<Class>();
		parameterList.add(boClass);
		updateMethodInfo = initMethod("public", "ConsoleReturnBO", "save" + boClass.getSimpleName().substring(0, boClass.getSimpleName().length() - 2), parameterList, null);
		classInfo.getMethodInfoList().add(updateMethodInfo);
		MethodInfo updateListMethodInfo = new MethodInfo();
		List<Class> parameter2List = new ArrayList<>();
		parameter2List.add(List.class);
		updateListMethodInfo = initMethod("public", "ConsoleReturnBO", "save" + boClass.getSimpleName().substring(0, boClass.getSimpleName().length() - 2), parameter2List, null);
		classInfo.getMethodInfoList().add(updateListMethodInfo);
	}

	private void initRemoveMethod(ClassInfo classInfo, Class boClass)
	{
		MethodInfo removeMethodInfo = new MethodInfo();
		List<Class> parameterList = new ArrayList<Class>();
		parameterList.add(boClass);
		removeMethodInfo = initMethod("public", "ConsoleReturnBO", "remove" + boClass.getSimpleName().substring(0, boClass.getSimpleName().length() - 2), parameterList, null);
		classInfo.getMethodInfoList().add(removeMethodInfo);
		MethodInfo removeListMethodInfo = new MethodInfo();
		List<Class> parameter2List = new ArrayList<>();
		parameter2List.add(List.class);
		removeListMethodInfo = initMethod("public", "ConsoleReturnBO", "remove" + boClass.getSimpleName().substring(0, boClass.getSimpleName().length() - 2), parameter2List, null);
		classInfo.getMethodInfoList().add(removeListMethodInfo);
	}

	private void initCountMethod(ClassInfo classInfo, Class infoClass)
	{
		MethodInfo countMethodInfo = new MethodInfo();
		List<Class> parameterList = new ArrayList<Class>();
		parameterList.add(infoClass);
		countMethodInfo = initMethod("public", "Long", "count" + infoClass.getSimpleName().substring(0, infoClass.getSimpleName().length() - 2), parameterList, null);
		classInfo.getMethodInfoList().add(countMethodInfo);
	}

	private MethodInfo initMethod(String accessModifier, String returnType, String methodName, List<Class> parameterList, List<Class> exceptionList)
	{
		MethodInfo methodInfo = new MethodInfo();
		methodInfo.setInterface(true);
		methodInfo.setAccessModifier(accessModifier);
		methodInfo.setReturnType(returnType);
		methodInfo.setMethodName(methodName);
		methodInfo.setParameterList(parameterList);
		methodInfo.setExceptionList(exceptionList);
		return methodInfo;
	}

	public String createInterface()
	{
		String returnString = null;
		StringBuffer interfaceBuffer = new StringBuffer();
		interfaceBuffer.append(getPackage(classInfo));
		interfaceBuffer.append(classInfo.getNote());
		interfaceBuffer.append(getImport(classInfo));
		interfaceBuffer.append(getClassHead(classInfo));
		interfaceBuffer.append("{");
		interfaceBuffer.append(getLogger(classInfo));
		interfaceBuffer.append(getClassField(classInfo));
		interfaceBuffer.append(getMehtod(classInfo));
		interfaceBuffer.append("}");
		returnString = interfaceBuffer.toString();
		return returnString;
	}

	private String getPackage(ClassInfo classInfo)
	{
		String returnString = null;
		if (StringUtils.isNotNullAndBlank(classInfo.getClassPackagePath()))
		{
			returnString = "package " + classInfo.getClassPackagePath() + ";\n";
		}
		return returnString;
	}

	private String getImport(ClassInfo classInfo)
	{
		String returnString = "";

		List<String> importList = classInfo.getImportList();
		if (importList != null && importList.size() > 0)
		{
			StringBuffer stringBuffer = new StringBuffer();
			for (String itemImport : importList)
			{
				stringBuffer.append("import " + itemImport + ";").append("\n");
			}
			returnString = stringBuffer.toString();
		}
		return returnString;
	}

	private String getClassHead(ClassInfo classInfo)
	{
		String returnString = "";

		StringBuffer stringBuffer = new StringBuffer();
		if (StringUtils.isNotNullAndBlank(classInfo.getAcceccModdifier()))
		{
			stringBuffer.append(classInfo.getAcceccModdifier());
		}
		else
		{
			stringBuffer.append("public");
		}
		if (StringUtils.isNotNullAndBlank(classInfo.getClassType()))
		{
			stringBuffer.append(" " + classInfo.getClassType());
		}
		else
		{
			stringBuffer.append(" class");
		}
		if (StringUtils.isNotNullAndBlank(classInfo.getClassName()))
		{
			stringBuffer.append(" " + classInfo.getClassName());
		}
		returnString = stringBuffer.toString();
		return returnString;
	}

	private String getLogger(ClassInfo classInfo)
	{
		String returnString = "";
		if (!classInfo.getClassType().equals("interface"))
		{
			StringBuffer loggerBuffer = new StringBuffer();
			loggerBuffer.append("Logger logger = LoggerFactory.getLogger(").append(classInfo.getClassName()).append(");").append("\n");
			returnString = loggerBuffer.toString();
		}
		return returnString;
	}

	private String getClassField(ClassInfo classInfo)
	{
		String returnString = "";

		List<FieldInfo> fieldInfoList = classInfo.getFieldInfoList();
		if (fieldInfoList != null && fieldInfoList.size() > 0)
		{
			StringBuffer fieldBuffer = new StringBuffer();
			for (FieldInfo fieldInfo : fieldInfoList)
			{
				fieldBuffer.append(fieldInfo);
			}
			returnString = fieldBuffer.toString();
		}
		return returnString;
	}

	private String getMehtod(ClassInfo classInfo)
	{
		String returnString = null;
		List<MethodInfo> methodInfoList = classInfo.getMethodInfoList();
		if (methodInfoList != null && methodInfoList.size() > 0)
		{
			StringBuffer methodBuffer = new StringBuffer();
			for (MethodInfo methodInfo : methodInfoList)
			{
				methodBuffer.append(methodInfo);
			}
			returnString = methodBuffer.toString();
		}
		return returnString;
	}

}
